package output;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import le.LexicalEntry;
import le.Pattern;
import le.ValenceUnit;

public class Argument  implements Comparable<Argument> {

	public String syntacticRole;
	public String syntacticCategory;
	public String pform = "";
	public SemanticRole semanticRole;
	public String core = "";
	
	public Argument(Dependent d,String fnId,String fnAnnoId,String fnDistro) throws IOException, ParserConfigurationException, SAXException {
		syntacticRole = d.syntacticRole;
		syntacticCategory = d.syntacticCategory;
		semanticRole = d.semanticRole;
		// get pform from relevant lexical file:
		if (d.syntacticCategory.equals("PP")) {
			LexicalEntry lex = new LexicalEntry(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(new File(fnDistro,"leXML"),"le"+fnId+".xml")).getDocumentElement());
			Pattern p = null;
			// find the pattern p with the same annoId:
			for (Pattern q: lex.patterns) {
				for (String id: q.annoIds) {
					if (id.equals(fnAnnoId)) {
						p = q;
						break;
					}
				}
				if (p!=null) break;
			}
			if (p!=null) {
				ValenceUnit v = null;
				// find the first valence unit with the same FE and PT
				for (ValenceUnit w: p.valenceUnits) {
					if (w.pt.startsWith("PP[") && w.fe.equals(d.semanticRole.name)) {
						v = w;
						break;
					}
				}
				if (v!=null) {
					pform = v.pt.substring(3,v.pt.length()-1);
				}
				else pform = "dum"; // no appropriate valence unit found for this FE PP
			}
			else pform = "bum"; // no pattern found for this fnAnnoId
		}
		else if (d.syntacticCategory.equals("PPing")) {
			LexicalEntry lex = new LexicalEntry(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(new File(fnDistro,"leXML"),"le"+fnId+".xml")).getDocumentElement());
			Pattern p = null;
			// find the pattern p with the same annoId:
			for (Pattern q: lex.patterns) {
				for (String id: q.annoIds) {
					if (id.equals(fnAnnoId)) {
						p = q;
						break;
					}
				}
				if (p!=null) break;
			}
			if (p!=null) {
				ValenceUnit v = null;
				// find the first valence unit with the same FE and PT
				for (ValenceUnit w: p.valenceUnits) {
					if (w.pt.startsWith("PPing[") && w.fe.equals(d.semanticRole.name)) {
						v = w;
						break;
					}
				}
				if (v!=null) {
					pform = v.pt.substring(6,v.pt.length()-1);
				}
				else pform = "dum"; // no valence unit found for this FE
			}
			else pform = "bum"; // no pattern found for this fnAnnoId
		}
		else if (d.syntacticCategory.equals("PPinterrog")) {
			LexicalEntry lex = new LexicalEntry(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(new File(fnDistro,"leXML"),"le"+fnId+".xml")).getDocumentElement());
			Pattern p = null;
			// find the pattern p with the same annoId:
			for (Pattern q: lex.patterns) {
				for (String id: q.annoIds) {
					if (id.equals(fnAnnoId)) {
						p = q;
						break;
					}
				}
				if (p!=null) break;
			}
			if (p!=null) {
				ValenceUnit v = null;
				// find the first valence unit with the same FE and PT
				for (ValenceUnit w: p.valenceUnits) {
					if (w.pt.startsWith("PPint") && w.fe.equals(d.semanticRole.name)) {
						v = w;
						break;
					}
				}
				if (v!=null) {
					pform = v.pt.substring(6,v.pt.length()-1);
				}
				else pform = "dum"; // no valence unit found for this FE
			}
			else pform = "bum"; // no pattern found for this fnAnnoId
		}
	}
	
	public Argument() {}
	
	public String toXML() {
		String s = "          <argument";
		s = s + " syntacticRole=\"";
		s = s + syntacticRole + "\" syntacticCategory=\"";
		s = s + syntacticCategory + "\" ";	
		if (!pform.equals("")) s = s + "pform=\"" + pform + "\" ";		
		if (!core.equals("")) s = s + "core=\"" + core + "\"";
		s = s + ">\n";
		s = s + semanticRole.toXML(12);				
		return s + "          </argument>\n";
	}
	
	public int compareTo(Argument a) {
		if (this.equals(a)) return 0;
		// Ext > Obj > Dep
		// Then PTs ordered alphabetically
		// Then FEs ordered alphabetically
		else if (!this.syntacticRole.equals(a.syntacticRole)) {
				if (this.syntacticRole.equals("Ext")) return -1;
				else if (a.syntacticRole.equals("Ext")) return 1;
				else if (this.syntacticRole.equals("Obj")) return -1;
				else if (a.syntacticRole.equals("Obj")) return 1;
				else if (this.syntacticRole.equals("Dep")) return -1;
				else if (a.syntacticRole.equals("Dep")) return 1;
				else return this.syntacticRole.compareTo(a.syntacticRole);
			}
			else if (!this.syntacticCategory.equals(a.syntacticCategory)) {
				return this.syntacticCategory.compareTo(a.syntacticCategory);
			}
			else return this.semanticRole.name.compareTo(a.semanticRole.name);
		}
	
	public boolean equals(Object o) {
		if (!(o instanceof Argument)) return false;
		else {
			Argument a = (Argument) o;
			return a.syntacticRole.equals(this.syntacticRole) 
			       && a.syntacticCategory.equals(this.syntacticCategory)
			       && a.pform.equals(this.pform)
			       && a.semanticRole.name.equals(this.semanticRole.name);
		}
	}
	
	public Argument clone() {
		Argument a = new Argument();
		a.syntacticRole = this.syntacticRole;
		a.syntacticCategory = this.syntacticCategory;
		a.pform = this.pform;
		a.core = this.core;
		a.semanticRole = this.semanticRole.clone();
		return a;
	}
	
	public Argument clone2() {
		Argument a = new Argument();
		a.syntacticRole = this.syntacticRole;
		a.syntacticCategory = this.syntacticCategory;
		a.pform = this.pform;
		a.core = this.core;
		a.semanticRole = this.semanticRole.clone2();
		return a;
	}
	
	public Argument clone3() {
		Argument a = new Argument();
		a.syntacticRole = this.syntacticRole;
		a.syntacticCategory = this.syntacticCategory;
		a.pform = this.pform;
		a.core = this.core;
		a.semanticRole = this.semanticRole.clone3();
		return a;
	}
	
}
